package com.tangding.net.coder;
import java.util.List;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.tangding.common.logx.LogHelp;
import com.tangding.common.utils.ByteUtil;
import com.tangding.common.utils.Utils;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageCodec;

/**
 * @description 包头6位保存真实数据长度
 * 
 * 				[0,0,x,y,0,0]
 * 真实数据长度为：x * 100 + y
 * 
 *
 * @author Ranger
 * @version 2014-4-29_上午9:37:59
 *
 */
public class GameCoderBack extends ByteToMessageCodec<byte[]> {

	private final int headLength = 6;
	
	int decodeTimesLimit = 100;//递归次数限制
	@Override
	protected void decode(ChannelHandlerContext ch, ByteBuf in, List<Object> reader) throws Exception {
		analyzeData(in, reader, 0);
	}
	
	private void analyzeData(ByteBuf in, List<Object> reader, int times) {
		if (times >= decodeTimesLimit) {
			LogHelp.doLogApp("decoder more than " + decodeTimesLimit + " times...");
			clear(in);//清理buf
			return;
		}
		int oneLength = in.readableBytes();
		if(oneLength < headLength) {//不够包头长度
			return;
		}
		byte[] head = new byte[headLength];
		in.readBytes(head, 0, head.length);//读取头部
		byte[] cache = null;
			//计算包长度
		int packLength = ByteUtil.getShort(head, 0);
		if(in.readableBytes() >= packLength) {//足够包长
			cache = new byte[packLength];
			in.readBytes(cache, 0, packLength);
			reader.add(cache);
			in.markReaderIndex();
			if(in.readableBytes() > 0) {//还有残留包体
				if(in.readableBytes() > head.length) {//够包头长度
					head = new byte[headLength];
					in.readBytes(head, 0, head.length);//读取头部
					in.resetReaderIndex();
					analyzeData(in, reader, times + 1);//递归处理
				}else {
					return;
				}
			}
		} else {
			in.resetReaderIndex();
			return;
		}
	}
	
	private void clear(ByteBuf buf) {
		buf.clear();
		buf.markReaderIndex();
		buf.resetReaderIndex();
		buf.markWriterIndex();
		buf.resetWriterIndex();
	}

	@Override
	protected void encode(ChannelHandlerContext ch, byte[] data, ByteBuf out) throws Exception {
		out.writeBytes(addHead(data));
	}
	
	
	//给数据添加头部
	private byte[] addHead(byte[] data) {
		byte a = 0;
		byte b = 0;
		if(data.length >= 100) {
			a = (byte)(data.length / 100);
		}
		b = (byte)(data.length % 100);
		byte[] head = {0, 0, a, b, 0, 0};
		short l = (short)data.length;
		ByteUtil.putShort(head, l, 0);
		return Utils.combineArray(head, data);
	}
}